<!-- 新增日报组件 -->
<script setup lang="ts">
import { ref, computed, reactive } from "vue"
import { selectJiraByProjectId } from "@/api/jira"
import { fetchSelectList } from "@/api/common"
import { type ReportData } from "@/api/report/types/report"
import * as ReportApi from "@/api/report"
import { type SelectData } from "@/api/common/types/common"
import { ElMessage, ElMessageBox, DrawerProps } from "element-plus"
import { CirclePlus, Refresh } from "@element-plus/icons-vue"
import { cloneDeep } from "lodash-es"
import dayjs from "dayjs"
import { JiraData } from "@/api/jira/types/jira"
import ImportJirasBtn from "@/components/jira/importJirasBtn.vue"

// 定义触发父组件的事件
const emit = defineEmits<{
  // 操作完成的事件, 主要是为了重新加载日报数据
  (event: "operation-complete"): void
}>()

//我的可选项目
const mineProjectSelectOptions = ref<SelectData[]>([])
const fetchMineProjectSelectOptions = async () => {
  const data = await fetchSelectList("mineProject")
  mineProjectSelectOptions.value = data.data
}
//#region 新增工时 抽屉 start *************************************
const today = (): string => {
  return dayjs().format("YYYY-MM-DD")
}
//#region 增

const drawer = ref<boolean>(false)
const direction = ref<DrawerProps["direction"]>("rtl")

// 用于存储每行数据每个字段的验证状态，初始化为空数组，后续对应每行添加一个对象来记录状态
const rowValidStates = reactive<Record<string, boolean>[]>([])
// 用于存储每个输入框旁边显示的验证提示信息，结构和验证状态对应
const validationMessages = reactive<Record<string, string>[]>([])

// 初始化校验状态
const initValidationStates = (index: number) => {
  rowValidStates[index] = {
    dateValid: true,
    projectIdValid: true,
    durationValid: true,
    jiraValid: true,
    contentValid: true
  }
  validationMessages[index] = {
    dateMessage: "",
    projectIdMessage: "",
    durationMessage: "",
    jiraMessage: "",
    contentMessage: ""
  }
}

// 校验单行数据
const validateRow = (row: ReportData, index: number) => {
  // 初始化校验状态
  initValidationStates(index)

  let validationPassed = true
  let errorMessage = ""

  // 校验日期
  if (!row.date) {
    rowValidStates[index].dateValid = false
    validationMessages[index].dateMessage = "日期必填"
    validationPassed = false
    errorMessage += "日期必填; "
  }

  // 校验项目ID
  if (!row.projectId) {
    rowValidStates[index].projectIdValid = false
    validationMessages[index].projectIdMessage = "所属项目必填"
    validationPassed = false
    errorMessage += "所属项目必填; "
  }

  // 校验工时
  if (!row.durationHour || row.durationHour < 0.5 || row.durationHour > 18) {
    rowValidStates[index].durationValid = false
    validationMessages[index].durationMessage = "工时需在0.5-18小时之间"
    validationPassed = false
    errorMessage += "工时需在0.5-18小时之间; "
  }

  // 校验Jira号
  if (!row.jira) {
    rowValidStates[index].jiraValid = false
    validationMessages[index].jiraMessage = "jira号必填"
    validationPassed = false
    errorMessage += "jira号必填; "
  }

  // 校验内容
  if (!row.content) {
    rowValidStates[index].contentValid = false
    validationMessages[index].contentMessage = "内容必填"
    validationPassed = false
    errorMessage += "内容必填; "
  }

  return { validationPassed, errorMessage }
}

const DEFAULT_REPOT_ROW: ReportData = {
  projectId: undefined,
  date: today(),
  jira: "",
  subJira: "",
  content: "",
  durationHour: 0.5,
  jiraDurationHour: 0,
  jiraUsedTimeHour: 0
}
const insertReportData = ref<ReportData[]>([])

// 存放某个项目 的可选任务 jira列表
const projectJIraOptionsMap = reactive<Map<number, JiraData[]>>(new Map<number, JiraData[]>())
// 存放某个项目 的可选 bug jira列表
const projectSubJIraOptionsMap = reactive<Map<number, JiraData[]>>(new Map<number, JiraData[]>())

//初始化新增日报列表
const initInsertReportData = () => {
  fetchMineProjectSelectOptions()
  // 如果已经有数据，则不执行操作
  if (insertReportData.value.length > 0) {
    return
  }
  insertReportData.value = [cloneDeep(DEFAULT_REPOT_ROW)]
  initValidationStates(0)
  projectJIraOptionsMap.clear()
  projectSubJIraOptionsMap.clear()
}

/**
 * 清除日报表单
 */
const cleanInsertReportData = () => {
  insertReportData.value = []
  rowValidStates.splice(0, rowValidStates.length)
  validationMessages.splice(0, validationMessages.length)
  fetchMineProjectSelectOptions()
  projectJIraOptionsMap.clear()
  projectSubJIraOptionsMap.clear()
}

//导入jira后，动态当前页面 项目下的jira列表
const afterImportJira = () => {
  projectJIraOptionsMap.forEach((jiras, projectId) => {
    fetchProjectJiraSelectOptions(projectId)
  })
}

// 计算日报条数的计算属性
const reportCount = computed(() => insertReportData.value.length)

// 计算总工时分钟数的计算属性，使用reduce方法累加duration属性
const totalDuration = computed(() =>
  insertReportData.value.reduce((acc, current) => {
    // 使用可选链运算符
    return acc + (current.durationHour?.valueOf() || 0)
  }, 0)
)

// 获取 项目下的任务jira 列表 和bugjira 列表
const fetchProjectJiraSelectOptions = async (projectId: number) => {
  const { data } = await selectJiraByProjectId(projectId)
  projectJIraOptionsMap.set(projectId, data)
  const { data: subData } = await selectJiraByProjectId(projectId, true)
  projectSubJIraOptionsMap.set(projectId, subData)
}
// 当项目变化时处理， 清除其选择的jira列表
const handleProjectChange = (row: ReportData) => {
  const selectedProject = mineProjectSelectOptions.value.find((project) => project.id === row.projectId)
  if (selectedProject) {
    // 不在手写  而是需要勾选
    // 当项目改变时且没有获取当前项目的jira列表时候，获取对应项目的jira列表
    if (row.projectId && !projectJIraOptionsMap.has(row.projectId)) {
      fetchProjectJiraSelectOptions(row.projectId)
    }
    row.jira = ""
    row.subJira = ""
    row.jiraDurationHour = 0
    row.jiraUsedTimeHour = 0
  }
}

// 当任务jira发生变化的时候 带出其工时情况
const handleJiraChange = (code: string, row: ReportData, _index: number) => {
  if (!row.projectId) return
  const jiraOptions: JiraData[] = projectJIraOptionsMap.get(row.projectId)!
  const jiraItem = jiraOptions?.find((item) => item.code === code)
  row.jiraDurationHour = jiraItem?.durationHour || 0
  row.jiraUsedTimeHour = jiraItem?.usedTimeHour || 0

  if (!row.content) {
    row.content = jiraItem?.content || ""
  }
}

// 新增一行
const addRow = () => {
  insertReportData.value.push(cloneDeep(DEFAULT_REPOT_ROW))
  initValidationStates(insertReportData.value.length - 1)
}

// 删除一行 同时删除校验结果
const removeRow = (row: ReportData) => {
  const index = insertReportData.value.indexOf(row)
  if (index !== -1) {
    insertReportData.value.splice(index, 1)
    rowValidStates.splice(index, 1)
    validationMessages.splice(index, 1)
  }
}

/* 复制一行*/
const copyRow = (row: ReportData) => {
  const index = insertReportData.value.indexOf(row)
  if (index !== -1) {
    // 使用展开运算符复制对象
    const copiedObject: ReportData = { ...row }
    insertReportData.value.push(copiedObject)
    rowValidStates.push({ ...rowValidStates[index] })
    validationMessages.push({ ...validationMessages[index] })
  }
}

//打开抽屉： 把这个方法暴露给父组件
const openDrawer = () => {
  drawer.value = true
  initInsertReportData()
}
// 暴露 openDrawer 方法给父组件
defineExpose({
  openDrawer
})

function confirmClick() {
  if (insertReportData.value.length == 0) return
  // 提交之前 手动触发一次全部数据校验
  for (let index = 0; index < insertReportData.value.length; index++) {
    const row = insertReportData.value[index]
    const { validationPassed, errorMessage } = validateRow(row, index)

    // 如果某行校验不通过，标记为不通过，并显示错误信息
    if (!validationPassed) {
      // 显示具体错误消息
      ElMessage.error(`第 ${index + 1} 行: ${errorMessage}`)
      // 一旦发现有不通过的行，直接退出
      return
    }
  }

  // 提交数据到后端
  ElMessageBox.confirm(`已填写工时[${totalDuration.value}]小时,确定提交数据吗? `, "提交", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(() => {
      ReportApi.batchInsertApi(insertReportData.value).then(() => {
        ElMessage.success("数据提交成功")
        emit("operation-complete")
        drawer.value = false
        cleanInsertReportData()
      })
    })
    .catch(() => {
      ElMessage.info("已取消提交")
    })
}

const cancelClick = () => {
  drawer.value = false
}
const cleanInsert = () => {
  ElMessageBox.confirm(`确认清空当前页面吗? 将失去编辑的内容`)
    .then(() => {
      cleanInsertReportData()
    })
    .catch(() => {
      // catch error
    })
}
//#endregion 新增工时 抽屉 end *************************************
</script>

<template>
  <!-- #region 批量新增工时 抽屉 start-->
  <el-drawer
    v-model="drawer"
    :direction="direction"
    size="80%"
    :close-on-click-modal="true"
    :close-on-press-escape="false"
    :with-header="false"
  >
    <template #default>
      <!-- <h4><el-text style="color: #67C23A;" size="large">新增工时</el-text></h4> -->
      <!-- 日报填报提醒 -->
      <div class="border-dotted border-l-2 border-r-2 p-1 mb-1 border-green-400">
        <el-collapse :v-model="[1]">
          <el-collapse-item name="1">
            <template #title>
              <el-text size="large" type="danger">日报填报提醒: </el-text> 可鼠标悬浮于表头上的<el-text type="primary"
                >[所属项目 | 任务Jira | Bug Jira]</el-text
              >上查看提示
            </template>

            <div class="ml-5">
              <el-text type="danger" size="large">任务 jira:</el-text> <br />
              <p class="ml-5">
                <el-text class="ml-10" type="primary">新需求项目</el-text
                >:JIRA编号包含项目的JIRA前缀，JIRA经办人为当前用户，JIRA类型为非BUG的所有JIRA(已经关联项目的jira则需要和当前选择的项目匹配)
                <br />
                <el-text class="ml-5" type="success">运维类项目:</el-text>
                JIRA编号包含项目的JIRA前缀，JIRA经办人为当前用户，JIRA类型为NOT in(New
                Feature、Improvement)(已经关联项目的jira则需要和当前选择的项目匹配)
              </p>
            </div>
            <div class="mx-5">
              <el-text type="danger" size="large">Bug jira:</el-text>
              <p class="ml-5">
                JIRA编号包含项目的JIRA前缀，JIRA经办人为当前用户，JIRA类型为BUG的所有JIRA(已经关联项目的jira则需要和当前选择的项目匹配)
              </p>
            </div>
          </el-collapse-item>
        </el-collapse>
      </div>

      <div class="toolbar-wrapper">
        <div>
          <el-button type="primary" :icon="CirclePlus" size="small" @click="addRow">新增一行</el-button>

          <el-button type="danger" :icon="Refresh" size="small" @click="cleanInsert">清空表单</el-button>

          <!--导入jira号 -->
          <ImportJirasBtn @set-loading="`emit('set-loading', true)`" @operation-complete="afterImportJira" />
        </div>
      </div>

      <div class="table-wrapper">
        <el-table :data="insertReportData" stripe :border="true" size="small">
          <el-table-column prop="date" label="日期" align="center" width="160">
            <template #default="{ row, $index }">
              <el-date-picker
                v-model="row.date"
                type="date"
                placeholder="选择日期"
                value-format="YYYY-MM-DD"
                size="small"
                style="max-width: 110px"
                @blur="validateRow(row, $index)"
              />
              <span v-if="!rowValidStates[$index].dateValid" style="color: red">{{
                validationMessages[$index].dateMessage
              }}</span>
            </template>
          </el-table-column>

          <el-table-column prop="projectId" label="所属项目" align="center">
            <template #header>
              <el-tooltip content="项目通过:类型、前缀、经办人等限制可选jira" placement="top" :open="true">
                <span>所属项目</span>
              </el-tooltip>
            </template>
            <template #default="{ row, $index }">
              <el-select
                v-model="row.projectId"
                clearable
                filterable
                placeholder="请选择项目"
                :empty-values="[null]"
                size="small"
                @change="handleProjectChange(row)"
                @blur="validateRow(row, $index)"
              >
                <el-option v-for="item in mineProjectSelectOptions" :key="item.id" :label="item.text" :value="item.id">
                  <span style="float: left">{{ item.text }}</span>
                  <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">
                    {{ item.additional }}
                  </span>
                </el-option>
              </el-select>
              <span v-if="!rowValidStates[$index].projectIdValid" style="color: red">{{
                validationMessages[$index].projectIdMessage
              }}</span>
            </template>
          </el-table-column>

          <el-table-column label="任务 Jira" prop="jira" align="center">
            <template #header>
              <el-tooltip content="新需求:非bug类型;运维:非New Feature、Improvement" placement="top">
                <span>任务 Jira</span>
              </el-tooltip>
            </template>
            <template #default="{ row, $index }">
              <!-- fetchProjectJiraSelectOptions -->
              <el-select
                v-model="row.jira"
                clearable
                filterable
                placeholder="请选择任务Jira"
                :empty-values="[null]"
                size="small"
                @change="(value) => handleJiraChange(value, row, $index)"
                @blur="validateRow(row, $index)"
              >
                <el-option
                  v-show="projectJIraOptionsMap.has(row.projectId)"
                  v-for="item in projectJIraOptionsMap.get(row.projectId)"
                  :key="item.code"
                  :label="item.code"
                  :value="item.code"
                >
                  <template #default>
                    <el-tooltip :content="item.content" placement="top" :show-after="200">
                      <span>{{ item.code }}</span>
                    </el-tooltip>
                  </template>
                </el-option>
              </el-select>
              <span v-if="!rowValidStates[$index].jiraValid" style="color: red">{{
                validationMessages[$index].jiraMessage
              }}</span>
            </template>
          </el-table-column>

          <el-table-column label="预估工时" prop="jiraDurationHour" align="center" width="80">
            <template #default="{ row }">
              <el-tag :type="'success'" effect="light" size="small"> {{ row.jiraDurationHour }} h </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="已用工时" prop="jiraUsedTimeHour" align="center" width="80">
            <template #default="{ row }">
              <!-- 如果 usedTimeHour 大于 durationHour，显示 el-tag -->
              <el-tag v-if="row.jiraUsedTimeHour > row.jiraDurationHour" :type="'danger'" effect="light" size="small">
                {{ row.jiraUsedTimeHour }} h
              </el-tag>
              <el-tag v-else :type="'info'" effect="light"> {{ row.jiraUsedTimeHour }} h </el-tag>
            </template>
          </el-table-column>

          <el-table-column label="Bug Jira" prop="subJira" align="center">
            <template #header>
              <el-tooltip content="非必填,只选Bug类型的Jira" placement="top">
                <span>Bug Jira</span>
              </el-tooltip>
            </template>
            <template #default="{ row }">
              <el-select
                v-model="row.subJira"
                clearable
                filterable
                placeholder="请选择Bug Jira"
                :empty-values="[null]"
                size="small"
              >
                <el-option
                  v-show="projectSubJIraOptionsMap.has(row.projectId)"
                  v-for="item in projectSubJIraOptionsMap.get(row.projectId)"
                  :key="item.code"
                  :label="item.code"
                  :value="item.code"
                >
                  <template #default>
                    <el-tooltip :content="item.content" placement="top" :show-after="200">
                      <span>{{ item.code }}</span>
                    </el-tooltip>
                  </template>
                </el-option>
              </el-select>
            </template>
          </el-table-column>

          <el-table-column label="工时" prop="durationHour" align="center">
            <template #default="{ row, $index }">
              <!-- <el-input-number v-model="row.duration" :min="1" :max="960" placeholder="单位:分钟"
                  @blur="handleDurationBlur(row, $index)" /> -->
              <el-input-number
                v-model="row.durationHour"
                :min="0.5"
                :max="18"
                :step="0.5"
                step-strictly
                controls-position="right"
                size="small"
                placeholder="单位:小时"
                @blur="validateRow(row, $index)"
              >
                <template #suffix>
                  <span>小时</span>
                </template>
              </el-input-number>

              <span v-if="!rowValidStates[$index].durationValid" style="color: red">{{
                validationMessages[$index].durationMessage
              }}</span>
            </template>
          </el-table-column>

          <el-table-column label="内容" prop="content" align="center" width="300">
            <template #default="{ row, $index }">
              <el-input
                type="textarea"
                v-model="row.content"
                placeholder="输入内容"
                style="width: 100%"
                :rows="3"
                @blur="validateRow(row, $index)"
                size="small"
              />
              <span v-if="!rowValidStates[$index].contentValid" style="color: red">{{
                validationMessages[$index].contentMessage
              }}</span>
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" align="center" width="80">
            <template #default="scope">
              <el-button type="danger" text bg size="small" @click="removeRow(scope.row)" class="my-1">删除</el-button
              ><br />
              <el-button type="success" text bg size="small" @click="copyRow(scope.row)">复制</el-button>
            </template>
          </el-table-column>
          <template #append>
            <div
              style="
                padding-left: 20px;
                background-color: rgb(179, 224.5, 156.5);
                font-size: 1em;
                height: 28px;
                line-height: 28px;
              "
            >
              已填写<el-text type="danger" size="large"> {{ reportCount }}</el-text
              >条日报, 共计工时 <el-text type="danger" size="large">{{ totalDuration }}</el-text> 小时
            </div>
          </template>
        </el-table>
      </div>
    </template>
    <template #footer>
      <div style="flex: auto">
        <el-button @click="cancelClick">关闭</el-button>
        <el-button type="primary" @click="confirmClick" :disabled="insertReportData.length == 0">提交</el-button>
      </div>
    </template>
  </el-drawer>
  <!-- #regionend 批量新增工时 抽屉 end-->
</template>

.
<style lang="scss" scoped>
.toolbar-wrapper {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

.table-wrapper {
  margin-bottom: 20px;
}
</style>
